package team.seekers.hula.audit.service;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import team.seekers.hula.audit.entity.dao.AuditDO;
import team.seekers.hula.audit.entity.dto.*;
import team.seekers.hula.audit.entity.vo.CheckPageVO;
import team.seekers.hula.audit.entity.vo.ReportPageVO;
import team.seekers.hula.audit.mapper.AuditMapper;
import team.seekers.hula.common.entity.PageResult;
import team.seekers.hula.common.entity.enums.AuditContentTypeEnum;
import team.seekers.hula.common.entity.enums.StatusEnum;
import team.seekers.hula.course.course.dao.CourseDao;
import team.seekers.hula.course.course.entity.dao.CourseDO;
import team.seekers.hula.course.course.service.CourseService;
import team.seekers.hula.course.resource.sectionContentComment.entity.dao.SectionContentCommentDO;
import team.seekers.hula.course.resource.sectionContentComment.service.SectionContentCommentService;
import team.seekers.hula.course.resource.sectionTalk.entity.dao.SectionTalkDO;
import team.seekers.hula.course.resource.sectionTalk.service.SectionTalkService;
import team.seekers.hula.island.island.service.IslandService;
import team.seekers.hula.island.post.entity.dao.IslandPostDO;
import team.seekers.hula.island.post.service.IslandPostService;
import team.seekers.hula.island.postComment.entity.dao.IslandPostCommentDO;
import team.seekers.hula.island.postComment.service.IslandPostCommentService;
import team.seekers.hula.message.message.entity.dto.MessageLetterDTO;
import team.seekers.hula.message.message.service.MessageService;
import team.seekers.hula.question.answer.entity.dao.AnswerDO;
import team.seekers.hula.question.answer.service.AnswerService;
import team.seekers.hula.question.answerComment.service.AnswerCommentService;
import team.seekers.hula.question.point.entity.dao.PointDO;
import team.seekers.hula.question.point.service.PointService;
import team.seekers.hula.question.question.entity.dao.QuestionDO;
import team.seekers.hula.question.question.service.QuestionService;
import team.seekers.hula.user.user.entity.dao.UserDO;
import team.seekers.hula.user.user.service.UserService;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Optional;

import static team.seekers.hula.common.entity.enums.AuditContentTypeEnum.*;
import static team.seekers.hula.common.entity.enums.MessageTypeEnum.QUESTION_POINT_WAIT;
import static team.seekers.hula.common.entity.enums.MessageTypeEnum.SPECIAL_QUESTION_WAIT;


@Service
public class AuditService extends ServiceImpl<AuditMapper, AuditDO> {

    @Autowired
    private AnswerService answerService;
    @Autowired
    private QuestionService questionService;
    @Autowired
    private PointService pointService;
    @Autowired
    private AnswerCommentService answerCommentService;
    @Autowired
    private CourseService courseService;
    @Autowired
    private UserService userService;
    @Autowired
    private IslandService islandService;
    @Autowired
    private SectionContentCommentService sectionContentCommentService;
    @Autowired
    private SectionTalkService sectionTalkService;
    @Autowired
    private MessageService messageService;
    @Autowired
    private IslandPostService islandPostService;
    @Autowired
    private IslandPostCommentService islandPostCommentService;
    @Autowired
    private CourseDao courseDao;



    /**
     * 举报
     * @param reportAddDto
     */
    public void report(ReportAddDTO reportAddDto) {
        AuditDO auditDO = new AuditDO();
        BeanUtils.copyProperties(reportAddDto,auditDO);
        auditDO.setType(1);
        auditDO.setContentType(AuditContentTypeEnum.getByType(reportAddDto.getType()));
        auditDO.setStatus(StatusEnum.WAIT);
        save(auditDO);
    }

    /**
     * 索存的问题和观点需要送审
     * @param checkAddDTO
     */
    public void check(CheckAddDTO checkAddDTO){
        // 敏感词过滤


        // 过滤审核内容，只有索存的问题和观点需要送审
        Integer type = checkAddDTO.getType();
        if (!AuditContentTypeEnum.getByType(type).equals(AuditContentTypeEnum.MODEXBEAN_QUESTION) ||
                !AuditContentTypeEnum.getByType(type).equals(MODEXBEAN_POINT)){
            return;
        }

        // 确定受理人
        AuditDO auditDO = new AuditDO();
        BeanUtils.copyProperties(checkAddDTO,auditDO);
        auditDO.setContentType(AuditContentTypeEnum.getByType(type));
        auditDO.setStatus(StatusEnum.WAIT);

        // 落库
        save(auditDO);

        // 发私信
        // TODO:确定负责人id
        LambdaQueryChainWrapper<CourseDO> query = courseDao.lambdaQuery();
        CourseDO one = query.select(CourseDO::getUserId).eq(CourseDO::getId, checkAddDTO.getLinkId()).one();
        MessageLetterDTO messageLetterDTO = new MessageLetterDTO();
        messageLetterDTO.setUserId(checkAddDTO.getUserId());
        messageLetterDTO.setLinkId(checkAddDTO.getLinkId());
        if(checkAddDTO.getType() == MODEXBEAN_QUESTION.getType() ){
            messageLetterDTO.setType(SPECIAL_QUESTION_WAIT);
        }else if(checkAddDTO.getType() == MODEXBEAN_POINT.getType()){
            messageLetterDTO.setType(QUESTION_POINT_WAIT);
        }
        messageLetterDTO.setDescription("待审核内容");
        messageLetterDTO.setToId(one.getUserId());
        messageService.letter(messageLetterDTO);

    }

    /**
     * 更新可见等级
     * @param updateVisibilityDTO
     */
    public void updateVisibility(UpdateVisibilityDTO updateVisibilityDTO){
        AuditContentTypeEnum type = AuditContentTypeEnum.getByType(updateVisibilityDTO.getType());
        String linkId = updateVisibilityDTO.getLinkId();
        Integer visibility = updateVisibilityDTO.getVisibility();
        switch (type) {
            case MODEXBEAN_ANSWER:
                AnswerDO answerDO = new AnswerDO();
                answerDO.setId(linkId);
                answerDO.setVisibility(visibility);
                answerService.updateById(answerDO);
                break;
            case MODEXBEAN_QUESTION:
                QuestionDO questionDO = new QuestionDO();
                questionDO.setId(linkId);
                questionDO.setVisibility(visibility);
                questionService.updateById(questionDO);
                break;
            case MODEXBEAN_POINT:
                PointDO pointDO = new PointDO();
                pointDO.setId(linkId);
                pointDO.setVisibility(visibility);
                pointService.updateById(pointDO);
                break;
//            case MODEXBEAN_ANSWER_COMMENT:
//                AnswerCommentDO answerCommentDO = new AnswerCommentDO();
//                answerCommentDO.setId(linkId);
//                answerCommentDO.
//                break;
            case ISLAND_POST:
                IslandPostDO islandPostDO = new IslandPostDO();
                islandPostDO.setId(linkId);
                islandPostDO.setVisibility(visibility);
                islandPostService.updateById(islandPostDO);
                break;
            case ISLAND_COMMENT:
                IslandPostCommentDO islandPostCommentDO = new IslandPostCommentDO();
                islandPostCommentDO.setId(linkId);
                islandPostCommentDO.setVisibility(visibility);
                islandPostCommentService.updateById(islandPostCommentDO);
                break;
            case PADDLE_COMMENT:
                SectionContentCommentDO sectionContentCommentDO = new SectionContentCommentDO();
                sectionContentCommentDO.setId(linkId);
                sectionContentCommentDO.setVisibility(visibility);
                sectionContentCommentService.updateById(sectionContentCommentDO);
                break;
            case PADDLE_SUGGESTION:
                SectionTalkDO sectionTalkDO = new SectionTalkDO();
                sectionTalkDO.setId(linkId);
                sectionTalkDO.setVisibility(visibility);
                sectionTalkService.updateById(sectionTalkDO);
                break;
        }

        // 是否需要级联更新审核表的内容
        if(StringUtils.isEmpty(updateVisibilityDTO.getAuditId())){
            return;
        }
        // 如果可见等级调整为全站可见，则表示通过，如果降为个人可见，则表示不通过
        AuditDO auditDO = new AuditDO();
        auditDO.setLinkId(updateVisibilityDTO.getLinkId());
        StatusEnum status = StatusEnum.WAIT;
        if(updateVisibilityDTO.getVisibility()==2) {
            status = StatusEnum.PASS;
        }else if(updateVisibilityDTO.getVisibility()==0){
            status = StatusEnum.FAIL;
        }
        UpdateWrapper<AuditDO> wrapper = new UpdateWrapper<>();
        wrapper.eq("link_id",linkId);
        wrapper.set("status",status.getType());
        update(wrapper);
    }


    public PageResult<CheckPageVO> getCheckList(CheckPageQueryDTO queryDTO) {
        // 用户昵称模糊查询
        LambdaQueryChainWrapper<UserDO> userQuery = userService.lambdaQuery();





        ArrayList<Integer> rangeType = new ArrayList<>();



        LambdaQueryChainWrapper<AuditDO> query = lambdaQuery();


        if(StringUtils.isNotBlank(queryDTO.getNickname())){
            ArrayList<String> userIdList = new ArrayList<>();
            for (UserDO userDO : userQuery.select(UserDO::getId).like(UserDO::getNickname, queryDTO.getNickname()).list()) {
                userIdList.add(userDO.getId());
            }
            if(userIdList.size() == 0) {
                return new PageResult<>();
            }
            query.in(AuditDO::getUserId,userIdList);
        }

        Optional.of(queryDTO).map(CheckPageQueryDTO::getContentType).ifPresent(type -> {
            query.eq(AuditDO::getContentType, AuditContentTypeEnum.getByType(type));
        });

        Optional.of(queryDTO).map(CheckPageQueryDTO::getStatus).ifPresent(status -> {
            query.eq(AuditDO::getStatus, StatusEnum.getByType(status));
        });

        if(StringUtils.isNotBlank(queryDTO.getSourceId())){
            query.eq(AuditDO::getSourceId,queryDTO.getSourceId());
        }

        // 表示送审
        query.eq(AuditDO::getType,0);
        // 只有求索板块的问题和观点需要送审，其他都是弱审核，靠举报
        rangeType.addAll(Arrays.asList(MODEXBEAN_QUESTION.getType(),MODEXBEAN_POINT.getType()));
        query.in(AuditDO::getContentType,rangeType);

        Page<AuditDO> pageResult = query.page(new Page<>(queryDTO.getPageNow(), queryDTO.getPageSize()));

        ArrayList<CheckPageVO> auditDTOS = new ArrayList<>();
        for (AuditDO record : pageResult.getRecords()) {
            CheckPageVO checkPageVO = new CheckPageVO();
            BeanUtils.copyProperties(record, checkPageVO);
            checkPageVO.setContentType(record.getContentType().getName());
            checkPageVO.setStatus(record.getStatus().getName());
            checkPageVO.setNickname(userService.getById(record.getUserId()).getNickname());
            auditDTOS.add(checkPageVO);
        }

        return new PageResult<>(pageResult.getTotal(), auditDTOS);
    }

    public PageResult<ReportPageVO> getReportList(ReportPageQueryDTO queryDTO) {



        LambdaQueryChainWrapper<AuditDO> query = lambdaQuery();

        Optional.of(queryDTO).map(ReportPageQueryDTO::getContentType).ifPresent(type -> {
            query.eq(AuditDO::getContentType, AuditContentTypeEnum.getByType(type));
        });

        // 用户昵称模糊查询
        if(StringUtils.isNotBlank(queryDTO.getNickname())){
            LambdaQueryChainWrapper<UserDO> userQuery = userService.lambdaQuery();
            ArrayList<String> userIdList = new ArrayList<>();
            for (UserDO userDO : userQuery.select(UserDO::getId).like(UserDO::getNickname, queryDTO.getNickname()).list()) {
                userIdList.add(userDO.getId());
            }
            if(userIdList.size() == 0) {
                return new PageResult<>();
            }
            query.in(AuditDO::getUserId, userIdList);
        }

        Optional.of(queryDTO).map(ReportPageQueryDTO::getStatus).ifPresent(status -> {
            query.eq(AuditDO::getStatus, StatusEnum.getByType(status));
        });

        Optional.of(queryDTO).map(ReportPageQueryDTO::getSourceId).ifPresent(sourceId -> {
            query.eq(AuditDO::getSourceId, sourceId);
        });

        ArrayList<Integer> rangeType = new ArrayList<>();
        // 确定筛选范围
        switch (queryDTO.getRange()){
            case 0:
                rangeType.addAll(Arrays.asList(MODEXBEAN_QUESTION.getType(),MODEXBEAN_POINT.getType(),MODEXBEAN_ANSWER.getType(),MODEXBEAN_ANSWER_COMMENT.getType()));
                break;
            case 1:
                rangeType.addAll(Arrays.asList(PADDLE_COMMENT.getType(),PADDLE_SUGGESTION.getType()));
                break;
            case 2:
                rangeType.addAll(Arrays.asList(ISLAND_POST.getType(),ISLAND_COMMENT.getType()));
                break;
        }
        if(rangeType.size()!=0){
            query.in(AuditDO::getContentType,rangeType);
        }
        // 表示举报
        query.eq(AuditDO::getType,1);
        query.orderByDesc(AuditDO::getGmtCreate);
        Page<AuditDO> pageResult = query.page(new Page<>(queryDTO.getPageNow(), queryDTO.getPageSize()));
        ArrayList<ReportPageVO> auditDTOS = new ArrayList<>();
        for (AuditDO record : pageResult.getRecords()) {

            ReportPageVO reportPageVO = new ReportPageVO();
            BeanUtils.copyProperties(record, reportPageVO);
            reportPageVO.setContentType(record.getContentType().getName());
            reportPageVO.setStatus(record.getStatus().getName());
            reportPageVO.setNickname(userService.getById(record.getUserId()).getNickname());
            auditDTOS.add(reportPageVO);
        }

        return new PageResult<>(pageResult.getTotal(), auditDTOS);
    }

    public void checkContent(CheckContentDTO checkContentDTO) {
        // 更新audit表
        AuditDO auditDO = new AuditDO();
        BeanUtils.copyProperties(checkContentDTO,auditDO);
        auditDO.setStatus(StatusEnum.PASS);
        updateById(auditDO);
        // 更新可见等级
        UpdateVisibilityDTO updateVisibilityDTO = new UpdateVisibilityDTO();
        updateVisibilityDTO.setVisibility(2);
        updateVisibilityDTO.setLinkId(checkContentDTO.getLinkId());
        updateVisibilityDTO.setType(checkContentDTO.getContextType());
        updateVisibility(updateVisibilityDTO);
    }
}
